﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITAP.ContourBuilder.Constraints;
using ITAP.ContourBuilder.Components.Constraints;
using ITAP.Core.Modelling.Primitives;
using System.Drawing;
using ITAP.Core.Modelling;


namespace ITAP.ContourBuilder.Components.Dimensions
{
    public class DimensionFactory
    {
        public static Dimension CreateContourElementDimension(ContourElement element, Font font, string prefixSymbol)
        {
            ContourElementDimension dimension = new ContourElementDimension();
            dimension.Font = font;
            DimensionFactory.InitializeDimension(dimension);
            dimension.Primitive = element.Primitive.Clone() as IPrimitive;
            dimension.PrefixSymbol = prefixSymbol;

            ContourConnectionProvider.Connect(dimension, element);

            return dimension;
        }

        private static void InitializeDimension(Dimension dimension)
        {
            List<IContourConstraint> constraints = (List<IContourConstraint>)dimension.Constraints;
            constraints.Add(new ConstraintRemoveInvalidDimension());
            constraints.Add(new ConstraintRecalculateDimension());
            
        }

        public static Dimension CreateArcHeightDimension(ContourElement element, Font font, string prefixSymbol)
        {
            ArcHeightDimension dimension = new ArcHeightDimension();
            dimension.Font = font;
            DimensionFactory.InitializeDimension(dimension);

            ModelPoint centerLinePoint = new ModelPoint((element.StartPoint.X + element.EndPoint.X) / 2, (element.StartPoint.Y + element.EndPoint.Y) / 2);
            ModelPoint centerArcPoint = element.Primitive.GetPoint(0.5);
            dimension.PrefixSymbol = prefixSymbol;

            ContourConnectionProvider.Connect(dimension, element);
            dimension.Recalculate();
            return dimension;
        }

        public static Dimension CreateArcRadiusDimension(ContourElement element, Font font, string prefixSymbol)
        {
            ArcRadiusDimension dimension = new ArcRadiusDimension();
            dimension.Font = font;
            DimensionFactory.InitializeDimension(dimension);
            dimension.PrefixSymbol = prefixSymbol;

            ContourConnectionProvider.Connect(dimension, element);
            dimension.Recalculate();
            return dimension;
        }

        public static Dimension CreateArcRadiusDimension2(ContourElement element, Font font, string prefixSymbol)
        {
            ArcRadiusDimension2 dimension = new ArcRadiusDimension2();
            dimension.Font = font;
            DimensionFactory.InitializeDimension(dimension);            
            dimension.PrefixSymbol = prefixSymbol;

            ContourConnectionProvider.Connect(dimension, element);
            dimension.Recalculate();
            return dimension;
        }

        public static Dimension CreateLeaderDimension(ContourElement element, Font font, string prefixSymbol)
        {
            ElementLeaderDimension dimension = new ElementLeaderDimension();
            dimension.Font = font;
            DimensionFactory.InitializeDimension(dimension);            
            dimension.PrefixSymbol = prefixSymbol;
            ContourConnectionProvider.Connect(dimension, element);
            dimension.Recalculate();
            return dimension;       
        }

        public static Dimension CreateComponentLeaderDimension(IContourComponent component1, IContourComponent component2, Font font, string prefixSymbol)
        {
            ComponentLeaderDimension dimension = new ComponentLeaderDimension();
            dimension.Font = font;

            DimensionFactory.InitializeDimension(dimension);

            dimension.PrefixSymbol = prefixSymbol;
            if (ContourConnectionProvider.Connect(dimension, component1) &&
                ContourConnectionProvider.Connect(dimension, component2))
            {
                dimension.Component1 = component1;
                dimension.Component2 = component2;
            }
            else
                throw new Exception("Невозможно соединить размер выноски с элементами.");

            dimension.Recalculate();
            return dimension;
        }

        public static Dimension CreateDiameterDimension(ContourHole hole, Font font, DiameterDimensionType type)
        {
            DiameterDimension dimension = new DiameterDimension();
            dimension.Type = DiameterDimensionType.Left;
            dimension.Font = font;
            DimensionFactory.InitializeDimension(dimension);
            ContourConnectionProvider.Connect(dimension, hole);
            dimension.Recalculate();
            return dimension;
        }

        public static Dimension CreateRemoteRadiusDimension(ContourElement element, Font font, string prefixSymbol)
        {
            RemoteRadiusDimension dimension = new RemoteRadiusDimension();
            dimension.Font = font;
            dimension.PrefixSymbol = prefixSymbol;
            DimensionFactory.InitializeDimension(dimension);
            ContourConnectionProvider.Connect(dimension, element);
            dimension.Recalculate();
            return dimension;
        }

        public static Dimension CreateDirectDistanceDimension(IContourComponent component1, IContourComponent component2, Font font, string prefixSymbol)
        {
            DirectDistanceDimension dimension = new DirectDistanceDimension();
            dimension.Font = font;

            DimensionFactory.InitializeDimension(dimension);

            dimension.PrefixSymbol = prefixSymbol;
            if (ContourConnectionProvider.Connect(dimension, component1) &&
                ContourConnectionProvider.Connect(dimension, component2))
            {
                dimension.Component1 = component1;
                dimension.Component2 = component2;
            }
            else
                throw new Exception("Невозможно создать размер дистанции.");

            dimension.Recalculate();
            return dimension;
        }

        public static Dimension CreateOffsetFromMainBorderDimension(ContourContainer container, Font font, string prefixSymbol, OffsetFromMainBorderDimensionType type)
        {
            OffsetFromMainBorderDimension dimension = new OffsetFromMainBorderDimension();
            dimension.Font = font;
            DimensionFactory.InitializeDimension(dimension);
            dimension.PrefixSymbol = prefixSymbol;
            dimension.Type = type;
            ContourConnectionProvider.Connect(dimension, container);

            dimension.Recalculate();
            return dimension;
        }
    }
}
